#include "qmemerydataview.h"

#include "qnewdatadialog.h"
#include "qremovedatadialog.h"

#include "../../libs/coreLib/styledbar.h"
#include "../../libs/sharedLib/qprojectcore.h"
#include "../../libs/sharedLib/qmemerymanager.h"
#include "../../libs/sharedLib/qvaluexml.h"
#include "../../libs/coreLib/qactiontoolbar.h"
#include "../../libs/coreLib/qsoftcore.h"
#include "../../libs/sharedLib/qnamevalidator.h"

#include <QHeaderView>

#include <QLineEdit>
#include <QHeaderView>
#include <QPainter>
#include <QApplication>
#include <QMouseEvent>
#include <QHBoxLayout>
#include <QLabel>
#include <QMouseEvent>
#include <QComboBox>
#include <QSpinBox>
#include <QMetaProperty>

static QIcon drawIndicatorIcon(const QPalette &palette,QStyle *style)
{
    QPixmap pix(14,14);

    pix.fill(Qt::transparent);

    QStyleOption branchOption;
    QRect r(QPoint(0,0),pix.size());
    branchOption.rect=QRect(2,2,9,9);
    branchOption.palette=palette;
    branchOption.state=QStyle::State_Children;

    QPainter p;
    p.begin(&pix);
    style->drawPrimitive(QStyle::PE_IndicatorBranch,&branchOption,&p);
    p.end();
    QIcon rc=pix;
    rc.addPixmap(pix,QIcon::Selected,QIcon::Off);
    branchOption.state |=QStyle::State_Open;

    pix.fill(Qt::transparent);
    p.begin(&pix);
    style->drawPrimitive(QStyle::PE_IndicatorBranch,&branchOption,&p);
    p.end();

    rc.addPixmap(pix,QIcon::Normal,QIcon::On);
    rc.addPixmap(pix,QIcon::Selected,QIcon::On);
    return rc;
}

QWidget *QMemeryDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/*option*/, const QModelIndex &index) const
{
    QWidget *ret=NULL;
    QTreeWidgetItem *item=m_listView->itemFromIndex(index);
    if(!m_listView->isGroupItem(item))
    {
        int col=index.column();
        if(col==0)
        {
            SHAREDLIB::QNameEdit *edit=new SHAREDLIB::QNameEdit("[_a-zA-Z0-9.]{,64}");
            SHAREDLIB::QMemeryManager *manager=SHAREDLIB::QProjectCore::getCore()->memeryManager();
            QStringList list=manager->namesList(item->parent()->text(0));
            list.removeAll(item->text(0));
            edit->setIntermediateList(list);
            ret=edit;
        }
        else if(col==1)
        {
            QComboBox *b=new QComboBox;
            b->addItems(SHAREDLIB::XMLValueFactory::supports());
            ret=b;
        }
        else if(col==2)
        {
            QObject* obj=m_listView->m_itemToObject.value(item);
            SHAREDLIB::XMLValue *v=SHAREDLIB::XMLValueFactory::create(obj->property("type").toString());
            if(v!=NULL)
            {
                ret=v->valueEditor();
                ret->metaObject()->userProperty().write(ret,obj->property("data"));
                delete v;
            }
        }
        else if(col==3)
        {
            QComboBox *b=new QComboBox;
            b->addItems(QStringList()<<"true"<<"false");
            ret=b;
        }
        else if(col==4)
        {
            QSpinBox *b=new QSpinBox;
            b->setRange(0,65535);
            ret=b;
        }
        else if(col==5)
        {
            ret=new QLineEdit;
        }
    }
    if(ret!=NULL)
    {
        ret->setParent(parent);
        ret->setProperty("no-ManhattanStyle",true);
        if(ret->inherits("QComboBox"))
        {
            QComboBox *b=(QComboBox*)ret;
            b->setCurrentIndex(b->findText(index.data().toString()));
        }
    }
    return ret;
}

void QMemeryDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &/*index*/) const
{
    editor->setGeometry(option.rect.adjusted(0,0,0,-1));
}

QSize QMemeryDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QSize size=QItemDelegate::sizeHint(option,index);
    size.setHeight(21);
    size.rwidth()+=4;
    return size;
}

void QMemeryDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
{
    QTreeWidgetItem* item=m_listView->itemFromIndex(index);
    QStyleOptionViewItemV3 opt=option;
    QColor c;
    if(item!=NULL)
    {
        if(m_listView->isGroupItem(item))
        {
            c=opt.palette.color(QPalette::Dark);
            opt.palette.setColor(QPalette::Text,opt.palette.color(QPalette::BrightText));
        }
        else
        {
            c=QColor(255,230,191);
            if(opt.features & QStyleOptionViewItemV2::Alternate)
            {
                c=c.lighter(112);
            }
        }
    }



    painter->fillRect(option.rect,c);
    opt.state &=~ QStyle::State_HasFocus;
    QItemDelegate::paint(painter,opt,index);
    opt.palette.setCurrentColorGroup(QPalette::Active);
    QColor color=static_cast<QRgb>(qApp->style()->styleHint(QStyle::SH_Table_GridLineColor,&opt));
    painter->setPen(color);

    if(!m_listView->isGroupItem(item))
    {
        if(index.column()!=m_listView->columnCount()-1)
        {
            int right=option.direction==Qt::LeftToRight?option.rect.right():option.rect.left();
            painter->drawLine(right,option.rect.y(),right,option.rect.bottom());
        }
    }
}

void QMemeryDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
{
    //QItemDelegate::setModelData(editor,model,index);
    QTreeWidgetItem* item=m_listView->itemFromIndex(index);
    QObject *obj=m_listView->m_itemToObject.value(item);
    if(index.column()==2)
    {
        SHAREDLIB::XMLValue* v=SHAREDLIB::XMLValueFactory::create(obj->property("type").toString());
        QVariant vvv=editor->metaObject()->userProperty().read(editor);
        if(editor->inherits("QComboBox"))
        {
            vvv=((QComboBox*)editor)->currentText();
        }
        v->setValue(vvv);
        model->setData(index,v->valueText());
        SHAREDLIB::QMemeryManager *mm=SHAREDLIB::QProjectCore::getCore()->memeryManager();
        mm->changedData(vvv,obj);
    }
    else
    {
        if(editor->inherits("QComboBox"))
        {
            QVariant v=editor->metaObject()->userProperty().read(editor);
            v=((QComboBox*)editor)->currentText();
            model->setData(index,v);
        }
        else
        {
            QItemDelegate::setModelData(editor,model,index);
        }
        if(index.column()==0)
        {
            if(obj->property("name").toString()!=index.data().toString())
            {
                SHAREDLIB::QMemeryManager *mm=SHAREDLIB::QProjectCore::getCore()->memeryManager();
                mm->changedName(index.data().toString(),obj);
            }
        }
        else if(index.column()==1)
        {
            QString type=index.data().toString();
            SHAREDLIB::XMLValue* v=SHAREDLIB::XMLValueFactory::create(type);
            obj->setProperty("type",type);
            obj->setProperty("data",v->value());
            model->setData(model->index(index.row(),2,index.parent()),v->valueText());
            delete v;
        }
        else if(index.column()==3)
        {
            obj->setProperty("hold",index.data());
        }
        else if(index.column()==4)
        {
            obj->setProperty("save",index.data());
        }
        else if(index.column()==5)
        {
            obj->setProperty("information",index.data());
        }

    }

}

QMemeryDataView::QMemeryDataView(QWidget *parent) :
    QTreeWidget(parent),
    m_styledBar(new CORELIB::StyledBar(this))
{
    QStringList list;
    list<<"Name"<<"Type"<<"Value"<<"Hold"<<"Save Period"<<"Information";
    setHeaderLabels(list);
    setAlternatingRowColors(true);
    setEditTriggers(QAbstractItemView::EditKeyPressed);
    setRootIsDecorated(false);
    header()->setMovable(false);
    setItemDelegate(new QMemeryDelegate(this));
    setFrameStyle(QFrame::NoFrame);

    m_expandIcon=drawIndicatorIcon(this->palette(),this->style());

    SHAREDLIB::QMemeryManager *mm=SHAREDLIB::QProjectCore::getCore()->memeryManager();
    connect(mm,SIGNAL(refresh()),this,SLOT(refresh()));
    connect(mm,SIGNAL(addDataSignal(QObject*)),this,SLOT(addData(QObject*)));
    connect(mm,SIGNAL(removeDataSignal(QObject*)),this,SLOT(removeData(QObject*)));


    CORELIB::QActionToolBar *toolbar=new CORELIB::QActionToolBar;

    QHBoxLayout *h=new QHBoxLayout;
    h->setContentsMargins(5,0,5,0);
    h->setSpacing(0);

    QLabel *label=new QLabel;
    label->setText(tr("Memery Manager"));
    label->setStyleSheet("color:rgb(255,255,255);");

    h->addWidget(label);
    h->addWidget(toolbar,1);

    m_styledBar->setLayout(h);

    QList<QAction*> aclist;
    QAction *ac;
    CORELIB::QSoftCore *core=CORELIB::QSoftCore::getCore();

    ac=new QAction(this);
    ac->setSeparator(true);
    aclist.append(ac);


    ac=core->action("DataManager-Add");
    if(ac!=NULL)
    {
        connect(ac,SIGNAL(triggered()),this,SLOT(add()));
        aclist.append(ac);
    }

    ac=core->action("DataManager-Del");
    if(ac!=NULL)
    {
        connect(ac,SIGNAL(triggered()),this,SLOT(remove()));
        aclist.append(ac);
    }

    ac=new QAction(this);
    ac->setSeparator(true);
    aclist.append(ac);

    toolbar->addButtonActions(aclist);

    connect(this,SIGNAL(clicked(QModelIndex)),this,SLOT(edit(QModelIndex)));
}

void QMemeryDataView::refresh()
{
    this->clear();
    SHAREDLIB::QMemeryManager *mm=SHAREDLIB::QProjectCore::getCore()->memeryManager();
    int count=mm->dataCount();
    QObject* obj;
    QTreeWidgetItem *item,*temp;
    QString group;
    QString type;
    for(int i=0;i<count;i++)
    {
        obj=mm->getData(i);
        group=obj->property("group").toString();
        if(group=="")
        {
            continue;
        }
        temp=m_groups.value(group);
        type=obj->property("type").toString();
        SHAREDLIB::XMLValue *v=SHAREDLIB::XMLValueFactory::create(type);
        if(v==NULL)
        {
            continue;
        }
        if(temp==NULL)
        {
            temp=new QTreeWidgetItem(this);
            temp->setText(0,group);
            temp->setIcon(0,m_expandIcon);
            m_groups.insert(group,temp);
            temp->setExpanded(true);
        }
        item=new QTreeWidgetItem(temp);
        item->setText(0,obj->property("name").toString());
        item->setText(1,type);
        item->setText(2,v->valueText());
        item->setText(3,obj->property("hold").toString());
        item->setText(4,obj->property("save").toString());
        item->setText(5,obj->property("information").toString());
        item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
        m_items.insert(obj->property("name").toString(),item);
        m_itemToObject.insert(item,obj);
        delete v;
    }
}

void QMemeryDataView::resizeEvent(QResizeEvent *event)
{
    QTreeWidget::resizeEvent(event);
    QRect re=contentsRect();
    m_styledBar->setGeometry(QRect(0,0,re.width(),m_styledBar->height()));
    header()->setGeometry(0,m_styledBar->height(),re.width(),header()->height());
    setViewportMargins(0,m_styledBar->height()+header()->height(),0,0);
}

bool QMemeryDataView::isGroupItem(QTreeWidgetItem *item)const
{
    return m_groups.values().contains(item);
}

void QMemeryDataView::add()
{
    QNewDataDialog dlg(this);
    dlg.exec();
}

void QMemeryDataView::remove()
{
    QRemoveDataDialog dlg(this);
    dlg.exec();
}

void QMemeryDataView::removeData(QObject *obj)
{
    QString name=obj->property("name").toString();
    QString group=obj->property("group").toString();
    QTreeWidgetItem *item=m_items.value(name);
    m_items.remove(name);
    if(item!=NULL)
    {
        m_itemToObject.remove(item);
        delete item;
    }
    item=m_groups.value(group);
    if(item!=NULL)
    {
        if(item->childCount()==0)
        {
            m_groups.remove(group);
            delete item;
        }
    }
}

void QMemeryDataView::addData(QObject *obj)
{
    QString group,type;
    QTreeWidgetItem *item,*temp;
    group=obj->property("group").toString();
    if(group=="")
    {
        return;
    }
    temp=m_groups.value(group);
    type=obj->property("type").toString();
    SHAREDLIB::XMLValue *v=SHAREDLIB::XMLValueFactory::create(type);
    if(v==NULL)
    {
        return;
    }
    if(temp==NULL)
    {
        temp=new QTreeWidgetItem(this);
        temp->setText(0,group);
        temp->setIcon(0,m_expandIcon);
        m_groups.insert(group,temp);
    }
    temp->setExpanded(true);
    item=new QTreeWidgetItem(temp);
    item->setText(0,obj->property("name").toString());
    item->setText(1,type);
    item->setText(2,v->valueText());
    item->setText(3,obj->property("hold").toString());
    item->setText(4,obj->property("save").toString());
    item->setText(5,obj->property("information").toString());
    m_items.insert(obj->property("name").toString(),item);
    item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsEditable);
    m_itemToObject.insert(item,obj);
    delete v;
}

void QMemeryDataView::mousePressEvent(QMouseEvent *event)
{
    QTreeWidget::mousePressEvent(event);

    QTreeWidgetItem *item=itemAt(event->pos());

    if(item)
    {
        if(m_groups.values().contains(item))
        {
            if(event->pos().x()+header()->offset()<20)
            {
                item->setExpanded(!item->isExpanded());
            }
        }
    }
}

void QMemeryDataView::clear()
{
    qDeleteAll(m_groups.values());
    m_groups.clear();
    m_items.clear();
    m_itemToObject.clear();
}

void QMemeryDataView::drawRow(QPainter *painter, const QStyleOptionViewItem &options, const QModelIndex &index) const
{
    QTreeWidgetItem* item=itemFromIndex(index);
    QStyleOptionViewItemV3 opt=options;
    QColor c;
    if(item!=NULL)
    {
        if(!m_groups.values().contains(item))
        {
            c=QColor(255,230,191);
            painter->fillRect(options.rect,c);
            opt.palette.setColor(QPalette::AlternateBase,c.lighter(112));
        }
        else
        {
            c=opt.palette.color(QPalette::Dark);
            painter->fillRect(options.rect,c);
            opt.palette.setColor(QPalette::AlternateBase,c);
        }
    }


    QTreeWidget::drawRow(painter,opt,index);

    QColor color=static_cast<QRgb>(QApplication::style()->styleHint(QStyle::SH_Table_GridLineColor));
    painter->setPen(color);
    painter->drawLine(opt.rect.x(),opt.rect.bottom(),opt.rect.right(),opt.rect.bottom());
}
